home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / pygtk / 2.0 / pygtk-demo.py
Text File  |  2006-01-20  |  11KB  |  319 lines

  1. #!/usr/bin/env python
  2. '''
  3.   $Id: pygtk-demo.py,v 1.8 2004/10/01 23:35:38 finlay Exp $
  4.  
  5.   pygtk-demo.py
  6.   2004-07-18: Some enhancements for building the demolist like in gtk-demos of the
  7.     gtk+ distribution.
  8.   2004-07-22: Simple syntaxhighlighting implemented, based on the tokenizer-module.
  9. '''
  10.  
  11. import string
  12. import re
  13. try:
  14.     import pygtk
  15.     pygtk.require('2.0')
  16. except ImportError:
  17.     pass
  18. import gobject
  19. import gtk
  20. import pango
  21.  
  22. # use for simple syntax highlighting ;-)
  23. import tokenize
  24. import keyword
  25.  
  26. import demos
  27. D_TEMPL = '%sDemo'
  28.  
  29. # Some programmatic definition for the testgtk_demos list. This avoids extra
  30. # maintenance if the demo list grows up. The current definition requires
  31. # a class or function with a swapped case name+'Demo' like in the doc string.
  32. # Swapped case is build from the __doc__-string programatically.
  33. child_demos = {}
  34. testgtk_demos = []
  35. for descr, mod in demos.demo_list:
  36.     # Find some categorized demos
  37.     try:
  38.         main, child = descr.split('/')
  39.     except ValueError:
  40.         # No, only one application
  41.         demo_class = D_TEMPL % re.sub('(\S+) *',
  42.             lambda m:(m.group(1)[0].isupper() and m.group(1) or m.group(1).capitalize()),
  43.             descr)
  44.         testgtk_demos.append((descr, mod, demo_class))
  45.     else:
  46.         # Ok. Some more testing
  47.         demo_class = D_TEMPL % re.sub('(\S+) *',
  48.             lambda m:(m.group(1)[0].isupper() and m.group(1) or m.group(1).capitalize()),
  49.             child)
  50.         try:
  51.             # Applicationgroup already defined?
  52.             child_demos[main.upper()].append((child, mod, demo_class))
  53.         except KeyError:
  54.             # No. Start a new category
  55.             child_demos.setdefault(main.upper(), []).append((child, mod, demo_class))
  56.             testgtk_demos.append((main, None, None, child_demos[main.upper()]))
  57.  
  58. (
  59.    TITLE_COLUMN,
  60.    MODULE_COLUMN,
  61.    FUNC_COLUMN,
  62.    ITALIC_COLUMN
  63. ) = range(4)
  64.  
  65. CHILDREN_COLUMN = 3
  66.  
  67. class InputStream(object):
  68.     ''' Simple Wrapper for File-like objects. [c]StringIO doesn't provide
  69.         a readline function for use with generate_tokens.
  70.         Using a iterator-like interface doesn't succeed, because the readline
  71.         function isn't used in such a context. (see <python-lib>/tokenize.py)
  72.     '''
  73.     def __init__(self, data):
  74.         self.__data = [ '%s\n' % x for x in data.splitlines() ]
  75.         self.__lcount = 0
  76.     def readline(self):
  77.         try:
  78.             line = self.__data[self.__lcount]
  79.             self.__lcount += 1
  80.         except IndexError:
  81.             line = ''
  82.             self.__lcount = 0
  83.         return line
  84.  
  85.  
  86. class PyGtkDemo(gtk.Window):
  87.     info_buffer = None
  88.     source_buffer = None
  89.     module_cache  = {}
  90.  
  91.     def __init__(self):
  92.         gtk.Window.__init__(self)
  93.         self.set_title("PyGTK+ Code Demos")
  94.         self.connect('destroy', lambda w: gtk.main_quit())
  95.         self.set_default_size(800, 400)
  96.  
  97.         hbox = gtk.HBox(False, 3)
  98.         self.add(hbox)
  99.  
  100.         treeview = self.__create_treeview()
  101.         hbox.pack_start(treeview, False, False)
  102.  
  103.         self.notebook = gtk.Notebook()
  104.         hbox.pack_start(self.notebook, expand=True)
  105.  
  106.         scrolled_window, self.info_buffer = self.__create_text(False)
  107.         self._new_notebook_page(scrolled_window, '_Info')
  108.         tag = self.info_buffer.create_tag('title')
  109.         tag.set_property('font', 'Sans 18')
  110.  
  111.         scrolled_window, self.source_buffer = self.__create_text(True)
  112.         self._new_notebook_page(scrolled_window, '_Source')
  113.         tag = self.source_buffer.create_tag('source')
  114.         tag.set_property('font', 'monospace')
  115.         tag.set_property('pixels_above_lines', 0)
  116.         tag.set_property('pixels_below_lines', 0)
  117.         tag = self.source_buffer.create_tag('keyword', foreground='#00007F',
  118.             weight=pango.WEIGHT_BOLD)
  119.         tag = self.source_buffer.create_tag('string', foreground='#7F007F')
  120.         tag = self.source_buffer.create_tag('comment', foreground='#007F00',
  121.             style=pango.STYLE_ITALIC)
  122.  
  123.         self.show_all()
  124.  
  125.     def run(self):
  126.         gtk.main()
  127.  
  128.     def _new_notebook_page(self, widget, label):
  129.         l = gtk.Label('')
  130.         l.set_text_with_mnemonic(label)
  131.         self.notebook.append_page(widget, l)
  132.  
  133.     def __create_treeview(self):
  134.         model = gtk.TreeStore(
  135.             gobject.TYPE_STRING,
  136.             gobject.TYPE_STRING,
  137.             gobject.TYPE_STRING,
  138.             gobject.TYPE_BOOLEAN
  139.         )
  140.  
  141.         treeview = gtk.TreeView(model)
  142.         selection = treeview.get_selection()
  143.         selection.set_mode(gtk.SELECTION_BROWSE)
  144.         treeview.set_size_request(200, -1)
  145.  
  146.         for module in testgtk_demos:
  147.             iter = model.append(None)
  148.             model.set(iter,
  149.                 TITLE_COLUMN, module[TITLE_COLUMN],
  150.                 MODULE_COLUMN, module[MODULE_COLUMN],
  151.                 FUNC_COLUMN, module[FUNC_COLUMN],
  152.                 ITALIC_COLUMN, False
  153.             )
  154.  
  155.             try:
  156.                 children = module[CHILDREN_COLUMN]
  157.                 for child_module in children:
  158.                     child_iter = model.append(iter)
  159.                     model.set(child_iter,
  160.                         TITLE_COLUMN, child_module[TITLE_COLUMN],
  161.                         MODULE_COLUMN, child_module[MODULE_COLUMN],
  162.                         FUNC_COLUMN, child_module[FUNC_COLUMN],
  163.                         ITALIC_COLUMN, False
  164.                     )
  165.             except IndexError:
  166.                 pass
  167.  
  168.         cell = gtk.CellRendererText()
  169.         cell.set_property('style', pango.STYLE_ITALIC)
  170.  
  171.         column = gtk.TreeViewColumn("Widget (double click for demo)", cell,
  172.             text=TITLE_COLUMN, style_set=ITALIC_COLUMN)
  173.  
  174.         treeview.append_column(column)
  175.  
  176.         selection.connect('changed', self.selection_changed_cb)
  177.         treeview.connect('row-activated', self.row_activated_cb)
  178.  
  179.         treeview.expand_all()
  180.  
  181.         return treeview
  182.  
  183.     def __create_text(self, is_source=False):
  184.         scrolled_window = gtk.ScrolledWindow()
  185.         scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  186.         scrolled_window.set_shadow_type(gtk.SHADOW_IN)
  187.  
  188.         text_view = gtk.TextView()
  189.         scrolled_window.add(text_view)
  190.  
  191.         buffer = gtk.TextBuffer(None)
  192.         text_view.set_buffer(buffer)
  193.         text_view.set_editable(False)
  194.         text_view.set_cursor_visible(False)
  195.  
  196.         text_view.set_wrap_mode(not is_source)
  197.  
  198.         return scrolled_window, buffer
  199.  
  200.     def row_activated_cb(self, treeview, path, column):
  201.         model = treeview.get_model()
  202.         iter  = model.get_iter(path)
  203.         module_name  = model.get_value(iter, MODULE_COLUMN)
  204.         func_name    = model.get_value(iter, FUNC_COLUMN)
  205.         italic_value = model.get_value(iter, ITALIC_COLUMN)
  206.         try:
  207.             self.module_cache[module_name].present()
  208.         except KeyError:
  209.             module = getattr(demos, module_name)
  210.             model.set(iter, ITALIC_COLUMN, not italic_value)
  211.             cmd = 'demos.%s.%s' % (module_name, func_name)
  212.             #print cmd
  213.             window = eval(cmd)(self)
  214.             if window:
  215.                 window.connect('destroy', self.window_closed_cb, model, path)
  216.                 self.module_cache[module_name] = window
  217.  
  218.     def selection_changed_cb(self, selection):
  219.         model, iter = selection.get_selected()
  220.         if not iter:
  221.             return False
  222.  
  223.         name = model.get_value(iter, MODULE_COLUMN)
  224.         self.load_module(name)
  225.  
  226.     def window_closed_cb (self, window, model, path):
  227.         iter = model.get_iter(path)
  228.         module_name  = model.get_value(iter, MODULE_COLUMN)
  229.         del self.module_cache[module_name]
  230.         italic_value = model.get_value(iter, ITALIC_COLUMN)
  231.         if italic_value:
  232.             model.set(iter, ITALIC_COLUMN, not italic_value)
  233.  
  234.  
  235.     def read_module(self, module):
  236.         filename = module.__file__
  237.         if filename[-4:] == '.pyc':
  238.             filename = filename[:-1]
  239.         fd = open(filename)
  240.         return fd.read()
  241.  
  242.     def insert_documentation(self, module):
  243.         buffer = self.info_buffer
  244.         iter = buffer.get_iter_at_offset(0)
  245.  
  246.         lines = string.split(module.__doc__ or '', '\n')
  247.         buffer.insert(iter, lines[0])
  248.         start = buffer.get_iter_at_offset(0)
  249.         buffer.apply_tag_by_name('title', start, iter)
  250.         buffer.insert(iter, '\n')
  251.         for line in lines[1:]:
  252.             buffer.insert(iter, line)
  253.             buffer.insert(iter, '\n')
  254.  
  255.     def clear_buffers(self):
  256.         start, end = self.info_buffer.get_bounds()
  257.         self.info_buffer.delete(start, end)
  258.  
  259.         start, end = self.source_buffer.get_bounds()
  260.         self.source_buffer.delete(start, end)
  261.  
  262.     def insert_source(self, data):
  263.         source_buffer = self.source_buffer
  264.         iter = source_buffer.get_iter_at_offset(0)
  265.  
  266.         last_erow, last_ecol = 0, 0
  267.         was_newline = False # multiline statement detection
  268.         for x in tokenize.generate_tokens(InputStream(data).readline):
  269.             # x has 5-tuples
  270.             tok_type, tok_str = x[0], x[1]
  271.             srow, scol = x[2]
  272.             erow, ecol = x[3]
  273.  
  274.             # The tokenizer 'eats' the whitespaces, so we have to insert this again
  275.             # if needed.
  276.             if srow == last_erow:
  277.                 # Same line, spaces between statements
  278.                 if scol != last_ecol:
  279.                     source_buffer.insert_with_tags_by_name(iter, ' '*(scol-last_ecol), 'source')
  280.             else:
  281.                 # New line.
  282.                 # First: Detect multiline statements. There is no special in the tokenizer stream.
  283.                 if was_newline is False and last_erow != 0:
  284.                     source_buffer.insert_with_tags_by_name(iter, ' \\\n', 'source')
  285.                 # new line check if it starts with col 0
  286.                 if scol != 0:
  287.                     source_buffer.insert_with_tags_by_name(iter, ' '*scol, 'source')
  288.             last_erow = erow
  289.             last_ecol = ecol
  290.  
  291.             if tok_type == tokenize.COMMENT:
  292.                 was_newline = True # newline is in tok_str included.
  293.                 source_buffer.insert_with_tags_by_name(iter, tok_str, 'source', 'comment')
  294.                 continue
  295.             elif tok_type == tokenize.NAME:
  296.                 if tok_str in keyword.kwlist:
  297.                     source_buffer.insert_with_tags_by_name(iter, tok_str, 'source', 'keyword')
  298.                     continue
  299.             elif tok_type == tokenize.STRING:
  300.                 source_buffer.insert_with_tags_by_name(iter, tok_str, 'source', 'string')
  301.                 continue
  302.  
  303.             # No special format for use. Check for newline.
  304.             was_newline = tok_type in (tokenize.NEWLINE, tokenize.NL)
  305.             source_buffer.insert_with_tags_by_name(iter, tok_str, 'source')
  306.  
  307.     def load_module(self, name):
  308.         self.clear_buffers()
  309.         if name is None: return
  310.         module = getattr(demos, name)
  311.         if module.__doc__:
  312.             self.insert_documentation(module)
  313.  
  314.         source = self.read_module(module)
  315.         self.insert_source(source)
  316.  
  317. if __name__ == '__main__':
  318.     PyGtkDemo().run()
  319.